package com.desay.pangoo.itmt.service.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.desay.pangoo.common.lite.lang.web.BusinessException;
import com.desay.pangoo.common.lite.lang.web.PangooWebConstant;
import com.desay.pangoo.common.lite.spring.web.ControllerCommonUtils;
import com.desay.pangoo.itmt.controller.vo.KeyTechRoadMapVo;
import com.desay.pangoo.itmt.entity.KeyTechRoadMapEntity;
import com.desay.pangoo.itmt.entity.ModifyLogEntity;
import com.desay.pangoo.itmt.entity.WorkGroupEntity;
import com.desay.pangoo.itmt.enums.DataBaseTableEnum;
import com.desay.pangoo.itmt.enums.ExceptionCodeEnum;
import com.desay.pangoo.itmt.repository.KeyTechRoadMapRepository;
import com.desay.pangoo.itmt.repository.WorkGroupRepository;
import com.desay.pangoo.itmt.repository.spec.ExpandCriteria;
import com.desay.pangoo.itmt.repository.spec.Restrictions;
import com.desay.pangoo.itmt.service.KeyRoadMapService;
import com.desay.pangoo.itmt.utils.CompareObjUtil;

import cn.hutool.core.collection.CollUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @author uidq1163
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class KeyRaodMapServiceImpl implements KeyRoadMapService {

	@Autowired
	KeyTechRoadMapRepository keyTechRoadMapRepository;

	@Autowired
	WorkGroupRepository workGroupRepository;

	@Autowired
	private ModifyLogServiceImpl modifyLogService;
	private static final String FIELD_WORKGROUP = "workGroup.id";

	@Override
	public Long create(KeyTechRoadMapVo vo) {
		String user = ControllerCommonUtils.getHeader(PangooWebConstant.HEADER_NAME_USER_FULL_NAME);
		KeyTechRoadMapEntity keyTechRoadMapEntity = new KeyTechRoadMapEntity();
		ExpandCriteria<KeyTechRoadMapEntity> c = new ExpandCriteria<>();
		// 根据组查询
		c.add(Restrictions.eq(FIELD_WORKGROUP, vo.getWorkGroupId(), true));
		c.add(Restrictions.eq("techName", vo.getTechName(), true));
		c.add(Restrictions.eq("techPtn", vo.getTechPtn(), true));

		List<KeyTechRoadMapEntity> list = keyTechRoadMapRepository.findAll(c);
		if (CollUtil.isNotEmpty(list)) {
			throw new BusinessException(ExceptionCodeEnum.PARENT_ROAD_MAP_NAME_OR_PTN_EXIST);
		}

		BeanUtils.copyProperties(vo, keyTechRoadMapEntity);
		// 检查是否属性年份数据
		if (null != vo.getParentId()) {
			Optional<KeyTechRoadMapEntity> opiton = keyTechRoadMapRepository.findById(vo.getParentId());
			if (opiton.isPresent()) {
				keyTechRoadMapEntity.setParent(opiton.get());
			} else {
				throw new BusinessException(ExceptionCodeEnum.PARENT_ROAD_MAP_NOT_EXIST);
			}
		}
		// 检查工作组是否存在
		if (null != vo.getWorkGroupId()) {
			Optional<WorkGroupEntity> option = workGroupRepository.findById(vo.getWorkGroupId());
			if (option.isPresent()) {
				keyTechRoadMapEntity.setWorkGroup(option.get());
			} else {
				throw new BusinessException(ExceptionCodeEnum.WORK_GROUP_NOT_EXIST);
			}
		} else {
			throw new BusinessException(ExceptionCodeEnum.WORK_GROUP_NOT_EMPTY);
		}

		// Name of Phases or Subsidiaries (Must have PTN)
		if (null != vo.getYear() && StringUtils.isEmpty(vo.getTechPtn())) {
			throw new BusinessException(ExceptionCodeEnum.ROAD_MAP_PTN_NOT_EXIST);
		}

		if (StringUtils.isNotEmpty(vo.getTechPtn())) {
			KeyTechRoadMapEntity ptnExist = keyTechRoadMapRepository.findByTechPtn(vo.getTechPtn());
			if (null != ptnExist) {
				throw new BusinessException(ExceptionCodeEnum.ROAD_MAP_TECHPTN_EXIST);
			}
		}
		keyTechRoadMapEntity.setCreator(user);
		keyTechRoadMapEntity = keyTechRoadMapRepository.save(keyTechRoadMapEntity);
		return keyTechRoadMapEntity.getId();
	}

	@Override
	public void delete(Long id) {
		Optional<KeyTechRoadMapEntity> opiton = keyTechRoadMapRepository.findById(id);
		if (!opiton.isPresent()) {
			throw new BusinessException(ExceptionCodeEnum.ROAD_MAP_NOT_EXIST);
		}
		// 有子级数据
		if (CollUtil.isNotEmpty(opiton.get().getPhases())) {
			throw new BusinessException(ExceptionCodeEnum.ROAD_MAP_CHILDREN_EXIST);
		}
		keyTechRoadMapRepository.deleteById(id);
	}

	@Override
	public void update(Long id, KeyTechRoadMapVo vo) {
		String user = ControllerCommonUtils.getHeader(PangooWebConstant.HEADER_NAME_USER_FULL_NAME);
		KeyTechRoadMapEntity keyTechRoadMapEntity = null;
		ExpandCriteria<KeyTechRoadMapEntity> c = new ExpandCriteria<>();
		// 根据组查询
		c.add(Restrictions.eq(FIELD_WORKGROUP, vo.getWorkGroupId(), true));
		c.add(Restrictions.eq("techName", vo.getTechName(), true));
		c.add(Restrictions.eq("techPtn", vo.getTechPtn(), true));
		c.add(Restrictions.ne("id", id, true));

		List<KeyTechRoadMapEntity> list = keyTechRoadMapRepository.findAll(c);
		if (CollUtil.isNotEmpty(list)) {
			throw new BusinessException(ExceptionCodeEnum.PARENT_ROAD_MAP_NAME_OR_PTN_EXIST);
		}
		Optional<KeyTechRoadMapEntity> opiton = keyTechRoadMapRepository.findById(id);
		if (opiton.isPresent()) {
			keyTechRoadMapEntity = opiton.get();
		} else {
			throw new BusinessException(ExceptionCodeEnum.ROAD_MAP_NOT_EXIST);
		}
		if (!vo.getVersion().equals(keyTechRoadMapEntity.getVersion())) {
			throw new BusinessException(ExceptionCodeEnum.DATA_VERSION_ERROR);
		}
		KeyTechRoadMapEntity oldEntity = CompareObjUtil.clone(keyTechRoadMapEntity);
		if (StringUtils.isNotEmpty(vo.getTechPtn())) {
			KeyTechRoadMapEntity ptnExist = keyTechRoadMapRepository.findByIdNotAndTechPtn(id, vo.getTechPtn());
			if (null != ptnExist) {
				throw new BusinessException(ExceptionCodeEnum.ROAD_MAP_TECHPTN_EXIST);
			}
		}
		BeanUtils.copyProperties(vo, keyTechRoadMapEntity, "id", "phases");
		// 是否有年份项目规划信息
		if (CollUtil.isNotEmpty(vo.getPhases())) {
			Set<KeyTechRoadMapEntity> phases = new HashSet<>();
			for (KeyTechRoadMapVo phase : vo.getPhases()) {
				KeyTechRoadMapEntity phaseEntity = null;
				// Name of Phases or Subsidiaries (Must have PTN)
				if (StringUtils.isEmpty(phase.getTechPtn())) {
					throw new BusinessException(ExceptionCodeEnum.ROAD_MAP_PTN_NOT_EXIST);
				}
				if (null != phase.getId()) {
					KeyTechRoadMapEntity ptnExist = keyTechRoadMapRepository.findByIdNotAndTechPtn(phase.getId(),
							phase.getTechPtn());
					if (null != ptnExist) {
						throw new BusinessException(ExceptionCodeEnum.ROAD_MAP_TECHPTN_EXIST);
					}
					// 编辑年份项目信息
					Optional<KeyTechRoadMapEntity> opitonPhase = keyTechRoadMapRepository.findById(phase.getId());
					if (opitonPhase.isPresent()) {
						phaseEntity = opitonPhase.get();
						phaseEntity.setUpdator(user);
					} else {
						throw new BusinessException(ExceptionCodeEnum.ROAD_MAP_NOT_EXIST);
					}
				} else {
					KeyTechRoadMapEntity ptnExist = keyTechRoadMapRepository.findByTechPtn(phase.getTechPtn());
					if (null != ptnExist) {
						throw new BusinessException(ExceptionCodeEnum.ROAD_MAP_TECHPTN_EXIST);
					}
					// 新增年份项目信息
					phaseEntity = new KeyTechRoadMapEntity();
					phaseEntity.setCreator(user);
				}
				// 检查是否属性年份数据
				if (null != phase.getParentId()) {
					Optional<KeyTechRoadMapEntity> opitonParent = keyTechRoadMapRepository
							.findById(phase.getParentId());
					if (opitonParent.isPresent()) {
						phaseEntity.setParent(opitonParent.get());
					} else {
						throw new BusinessException(ExceptionCodeEnum.PARENT_ROAD_MAP_NOT_EXIST);
					}
				} else {
					throw new BusinessException(ExceptionCodeEnum.PARENT_ROAD_MAP_NOT_EMPTY);
				}
				// 检查工作组是否存在
				if (null != phase.getWorkGroupId()) {
					Optional<WorkGroupEntity> option = workGroupRepository.findById(phase.getWorkGroupId());
					if (option.isPresent()) {
						phaseEntity.setWorkGroup(option.get());
					} else {
						throw new BusinessException(ExceptionCodeEnum.WORK_GROUP_NOT_EXIST);
					}
				} else {
					throw new BusinessException(ExceptionCodeEnum.WORK_GROUP_NOT_EMPTY);
				}
				BeanUtils.copyProperties(phase, phaseEntity, "id", "phases");
				phases.add(phaseEntity);
			}
			keyTechRoadMapEntity.setPhases(phases);
		} else {
			keyTechRoadMapEntity.setPhases(null);
		}
		keyTechRoadMapEntity.setUpdator(user);
		keyTechRoadMapEntity = keyTechRoadMapRepository.save(keyTechRoadMapEntity);
		// 保存修改日志
		writeLog(keyTechRoadMapEntity, oldEntity);
	}

	/**
	 * 记录日志
	 * 
	 * @param keyTechRoadMapEntity
	 * @param oldEntity
	 */
	private void writeLog(KeyTechRoadMapEntity keyTechRoadMapEntity, KeyTechRoadMapEntity oldEntity) {
		try {
			KeyTechRoadMapEntity newEntity = CompareObjUtil.clone(keyTechRoadMapEntity);
			if (null != oldEntity && null != newEntity) {
				// 保存修改日志
				// 不需要比较的字段:工作组
				newEntity.setWorkGroup(null);
				oldEntity.setWorkGroup(null);
				// 所属父级
				newEntity.setParent(null);
				oldEntity.setParent(null);

				if (CollUtil.isNotEmpty(newEntity.getPhases())) {
					newEntity.getPhases().forEach(a -> {
						a.setParent(null);
						a.setWorkGroup(null);
					});
				} else {
					newEntity.setPhases(null);
				}
				if (CollUtil.isNotEmpty(oldEntity.getPhases())) {
					oldEntity.getPhases().forEach(a -> {
						a.setParent(null);
						a.setWorkGroup(null);
					});
				} else {
					oldEntity.setPhases(null);
				}

				List<?> diffs = CompareObjUtil.compareObj(oldEntity, newEntity);
				if (CollUtil.isNotEmpty(diffs)) {
					ModifyLogEntity modifyLogEntity = new ModifyLogEntity();
					modifyLogEntity.setAssociatedId(keyTechRoadMapEntity.getId());
					modifyLogEntity.setAssociatedTable(DataBaseTableEnum.KEY_TECH_ROAD_MAP.getName());
					modifyLogEntity.setDetails(JSON.toJSONString(diffs, SerializerFeature.WriteMapNullValue));
					modifyLogService.saveLog(modifyLogEntity);
				}
			}

		} catch (Exception e) {
			log.error("写入数据集log失败：{}", e);
		}
	}

	@Override
	public Page<KeyTechRoadMapEntity> getList(Integer pageSize, Integer pageNum, Long workGroupId) {
		ExpandCriteria<KeyTechRoadMapEntity> c = new ExpandCriteria<>();
		// 根据组查询
		c.add(Restrictions.eq(FIELD_WORKGROUP, workGroupId, true));
		// 只取第一级
		c.add(Restrictions.isNull("parent"));
		List<Order> orders = new ArrayList<>();
		Order order = new Order(Sort.Direction.ASC, "createTime");
		orders.add(order);
		Pageable pageReq = PageRequest.of(pageNum - 1, pageSize, Sort.by(orders));
		return keyTechRoadMapRepository.findAll(c, pageReq);
	}

	@Override
	public KeyTechRoadMapEntity getById(Long id) {
		Optional<KeyTechRoadMapEntity> opiton = keyTechRoadMapRepository.findById(id);
		if (!opiton.isPresent()) {
			throw new BusinessException(ExceptionCodeEnum.ROAD_MAP_NOT_EXIST);
		}
		return opiton.get();
	}

}
